﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace AutofacDemo.IocResolver
{
    /// <summary>
    /// 依赖注入构建器基类，从程序集中反射进行依赖注入接口与实现的注册
    /// </summary>
    public abstract class IocBuilderBase : IIocBuilder
    {
        private static readonly IDictionary<string, Assembly[]> AssembliesesDict = new Dictionary<string, Assembly[]>();
        private readonly IServiceCollection _services;
        private bool _isBuilded;
        private IServiceProvider _provider;
        private  string _path;

        /// <summary>
        /// 初始化一个<see cref="IocBuilderBase"/>类型的新实例
        /// </summary>
        /// <param name="services">服务信息集合</param>
        protected IocBuilderBase(IServiceCollection services)
        {
            //AssemblyFinder = new DirectoryAssemblyFinder();
            _path = GetBinPath();
            _services = services.Clone();
        }

        /// <summary>
        /// 获取或设置 程序集查找器
        /// </summary>
        //public IAllAssemblyFinder AssemblyFinder { get; set; }

        /// <summary>
        /// 获取 服务提供者
        /// </summary>
        public IServiceProvider ServiceProvider
        {
            get
            {
                if (_isBuilded)
                {
                    return _provider;
                }
                _provider = Build();
                _isBuilded = true;
                return _provider;
            }
        }

        /// <summary>
        /// 开始构建依赖注入映射
        /// </summary>
        /// <returns>服务提供者</returns>
        public IServiceProvider Build()
        {
            if (_isBuilded)
            {
                return _provider;
            }

            //设置各个框架的DependencyResolver
            Assembly[] assemblies = FindAll();

            AddCustomTypes(_services);

            _provider = BuildAndSetResolver(_services, assemblies);
            _isBuilded = true;
            return _provider;
        }
        /// <summary>
        /// 查找所有项
        /// </summary>
        /// <returns></returns>
        public Assembly[] FindAll()
        {

            if (AssembliesesDict.ContainsKey(_path))
            {
                return AssembliesesDict[_path];
            }
            string[] files = Directory.GetFiles(_path, "*.dll", SearchOption.TopDirectoryOnly)
                .Concat(Directory.GetFiles(_path, "*.exe", SearchOption.TopDirectoryOnly))
                .ToArray();
            Assembly[] assemblies = files.Select(Assembly.LoadFrom).Distinct().ToArray();
            AssembliesesDict.Add(_path, assemblies);
            return assemblies;
        }

        private static string GetBinPath()
        {
            string path = AppDomain.CurrentDomain.BaseDirectory;
            return path == Environment.CurrentDirectory + "\\" ? path : Path.Combine(path, "bin");
        }
        /// <summary>
        /// 添加自定义服务映射
        /// </summary>
        /// <param name="services">服务信息集合</param>
        protected virtual void AddCustomTypes(IServiceCollection services)
        { }

        /// <summary>
        /// 重写以实现构建服务并设置各个平台的Resolver
        /// </summary>
        /// <param name="services">服务映射信息集合</param>
        /// <param name="assemblies">要检索的程序集集合</param>
        /// <returns>服务提供者</returns>
        protected abstract IServiceProvider BuildAndSetResolver(IServiceCollection services, Assembly[] assemblies);
    }
}
